package io.github.shenbinglife.springboot2.layui.admin.dao;

import io.github.shenbinglife.springboot2.layui.admin.entity.Role;
import io.github.shenbinglife.springboot2.layui.admin.entity.RoleMenuRelation;
import io.github.shenbinglife.springboot2.layui.admin.entity.RoleUserRelation;
import io.github.shenbinglife.springboot2.layui.admin.entity.User;
import io.github.shenbinglife.springboot2.layui.common.jpa.IBaseRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import javax.persistence.EntityManager;
import java.util.List;

@Repository
public interface RoleDao extends IBaseRepository<Role, Long> {

    @Query("select r from RoleUserRelation r where r.roleId=:roleId")
    List<RoleUserRelation> findUserRelationByRoleId(Long roleId);

    @Query("select r from RoleUserRelation r where r.userId=:userId")
    List<RoleUserRelation> findUserRelationByUserId(Long userId);

    default void addUserToRole(Long roleId, Long... userIds) {
        EntityManager em = getEm();
        for (Long userId : userIds) {
            em.persist(new RoleUserRelation(roleId, userId));
        }
    }

    @Query(value = "select d from Role d where :keyword is null" +
            " or d.code like CONCAT('%',:keyword,'%') " +
            " or d.name like CONCAT('%',:keyword,'%')")
    Page<Role> findByKeywordWithPagination(@Param("keyword") String keyword, Pageable pageable);

    @Query("select u from User u inner join RoleUserRelation r on u.id = r.userId where r.roleId=:roleId")
    List<User> findUsersByRoleId(Long roleId);

    @Query("select u from User u inner join RoleUserRelation r on u.id = r.userId where r.roleId=:roleId " +
            "and (:keyword is null or u.name like CONCAT('%',:keyword,'%') or " +
            " u.account like CONCAT('%',:keyword,'%') )")
    Page<User> findUsersByRoleIdWithPagination(Long roleId, String keyword, Pageable pageRequest);

    @Modifying
    @Query("delete from RoleUserRelation  r where r.roleId =:roleId and r.userId =:userId")
    void removeUsersFromRole(Long roleId, Long userId);

    @Modifying
    @Query("delete from RoleUserRelation  r where r.userId =:userId")
    void removeRelationByUserId(Long userId);

    @Modifying
    @Query("delete from RoleUserRelation  r where r.roleId =:roleId")
    void removeRelationByRoleId(Long roleId);

    @Query("select r from Role r inner join RoleUserRelation re on re.roleId = r.id" +
            " where re.userId=:userId")
    List<Role> findRolesByUserId(Long userId);

    List<Role> findByScope(String scope);

    @Modifying
    @Query("update Role  r set r.enabled=:enabled where r.id=:roleId")
    void updateEnabled(Long roleId, Boolean enabled);

    @Query("select r  from RoleMenuRelation r where r.roleId=:roleId")
    List<RoleMenuRelation> findMenusByRoleId(Long roleId);

    @Modifying
    @Query("delete from RoleMenuRelation r where r.roleId=:roleId")
    void removeMenuRelationByRoleId(Long roleId);

    default void addMenuToRole(Long roleId, Long... menuIds) {
        EntityManager em = getEm();
        for (Long menuId : menuIds) {
            em.persist(new RoleMenuRelation(roleId, menuId));
        }
    }
}
